<!doctype html>



  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.1" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="java,spring,mina," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.1" />






<meta name="description" content="spring集成mina 在学习mina这块时，在网上找了很多资料，只有一些demo，只能实现客户端向服务端发送消息、建立长连接之类。但是实际上在项目中，并不简单实现这些，还有业务逻辑之类的处理以及消息的推送之类的。于是就单独建立了一个工程项目，能够实现客户端和服务端相互之间发送消息、建立长连接、实现心跳检测等功能。例如:可以实现客户端A向服务端发送消息，服务端将消息转发给客户端B。 效果实现图">
<meta name="keywords" content="java,spring,mina">
<meta property="og:type" content="article">
<meta property="og:title" content="spring集成mina 实现消息推送以及转发">
<meta property="og:url" content="http://yoursite.com/2017/06/14/pancm36/index.html">
<meta property="og:site_name" content="虚无境的博客">
<meta property="og:description" content="spring集成mina 在学习mina这块时，在网上找了很多资料，只有一些demo，只能实现客户端向服务端发送消息、建立长连接之类。但是实际上在项目中，并不简单实现这些，还有业务逻辑之类的处理以及消息的推送之类的。于是就单独建立了一个工程项目，能够实现客户端和服务端相互之间发送消息、建立长连接、实现心跳检测等功能。例如:可以实现客户端A向服务端发送消息，服务端将消息转发给客户端B。 效果实现图">
<meta property="og:image" content="http://img.blog.csdn.net/20170614220230745?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:image" content="http://img.blog.csdn.net/20170614220337043?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:image" content="http://img.blog.csdn.net/20170614220412669?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:image" content="http://img.blog.csdn.net/20170614220520497?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:image" content="http://img.blog.csdn.net/20170614232518388?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">
<meta property="og:updated_time" content="2017-12-16T10:52:28.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="spring集成mina 实现消息推送以及转发">
<meta name="twitter:description" content="spring集成mina 在学习mina这块时，在网上找了很多资料，只有一些demo，只能实现客户端向服务端发送消息、建立长连接之类。但是实际上在项目中，并不简单实现这些，还有业务逻辑之类的处理以及消息的推送之类的。于是就单独建立了一个工程项目，能够实现客户端和服务端相互之间发送消息、建立长连接、实现心跳检测等功能。例如:可以实现客户端A向服务端发送消息，服务端将消息转发给客户端B。 效果实现图">
<meta name="twitter:image" content="http://img.blog.csdn.net/20170614220230745?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2017/06/14/pancm36/"/>






  <title>spring集成mina 实现消息推送以及转发 | 虚无境的博客</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?39c177d10f6e05ddfa113e02139b9c1c";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>










</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">虚无境的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/06/14/pancm36/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="虚无境">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/xuwujing.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="虚无境的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">spring集成mina 实现消息推送以及转发</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-06-14T23:11:00+08:00">
                2017-06-14
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/java/" itemprop="url" rel="index">
                    <span itemprop="name">java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        <script src="\assets\js\APlayer.min.js"> </script><h2 id="spring集成mina"><a href="#spring集成mina" class="headerlink" title="spring集成mina"></a>spring集成mina</h2><hr>
<p>在学习mina这块时，在网上找了很多资料，只有一些<a href="http://blog.csdn.net/qazwsxpcm/article/details/71438737" target="_blank" rel="external">demo</a>，只能实现客户端向服务端发送消息、建立长连接之类。但是实际上在项目中，并不简单实现这些，还有业务逻辑之类的处理以及消息的推送之类的。于是就单独建立了一个工程项目，能够实现客户端和服务端相互之间发送消息、建立长连接、实现心跳检测等功能。<br>例如:可以实现客户端A向服务端发送消息，服务端将消息转发给客户端B。</p>
<h3 id="效果实现图"><a href="#效果实现图" class="headerlink" title="效果实现图"></a>效果实现图</h3><h4 id="服务端启动成功后，-客户端A绑定服务端。"><a href="#服务端启动成功后，-客户端A绑定服务端。" class="headerlink" title="服务端启动成功后， 客户端A绑定服务端。"></a>服务端启动成功后， 客户端A绑定服务端。</h4><p><img src="http://img.blog.csdn.net/20170614220230745?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h4 id="客户端B向服务端发送信息，请求服务端向客户端A推送消息"><a href="#客户端B向服务端发送信息，请求服务端向客户端A推送消息" class="headerlink" title="客户端B向服务端发送信息，请求服务端向客户端A推送消息"></a>客户端B向服务端发送信息，请求服务端向客户端A推送消息</h4><p><img src="http://img.blog.csdn.net/20170614220337043?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h4 id="客户端A受到服务端转发的客户端B的消息"><a href="#客户端A受到服务端转发的客户端B的消息" class="headerlink" title="客户端A受到服务端转发的客户端B的消息"></a>客户端A受到服务端转发的客户端B的消息</h4><p><img src="http://img.blog.csdn.net/20170614220412669?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h4 id="服务端心跳检测的实现"><a href="#服务端心跳检测的实现" class="headerlink" title="服务端心跳检测的实现"></a>服务端心跳检测的实现</h4><p><img src="http://img.blog.csdn.net/20170614220520497?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<h4 id="代码的目录结构"><a href="#代码的目录结构" class="headerlink" title="代码的目录结构"></a>代码的目录结构</h4><p><img src="http://img.blog.csdn.net/20170614232518388?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWF6d3N4cGNt/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<p>那么开始实现代码的编写。(可以直接跳到底部，通过链接下载工程代码)<br>首先在官网上下载mina以及spring相关架包，这里相关架包已准备好:<a href="http://download.csdn.net/detail/qazwsxpcm/9870787" target="_blank" rel="external">http://download.csdn.net/detail/qazwsxpcm/9870787</a></p>
<h2 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h2><p>====</p>
<h3 id="首先实现数据传输对象、消息常量的代码编写。"><a href="#首先实现数据传输对象、消息常量的代码编写。" class="headerlink" title="首先实现数据传输对象、消息常量的代码编写。"></a>首先实现数据传输对象、消息常量的代码编写。</h3><hr>
<p> 我使用的两个传输对象，接受和发送，代码如下。(传输对象可以自行定义)。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.model;</div><div class="line"></div><div class="line">import java.io.Serializable;</div><div class="line">import java.util.HashMap;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description 服务端接收消息对象</div><div class="line"> */</div><div class="line">public class SentBody implements Serializable &#123;</div><div class="line"></div><div class="line">	private static final long serialVersionUID = 1L;</div><div class="line"></div><div class="line">	private String key;</div><div class="line"></div><div class="line">	private HashMap&lt;String, String&gt; data;</div><div class="line"></div><div class="line">	private long timestamp;</div><div class="line"></div><div class="line">	public SentBody() &#123;</div><div class="line">		data = new HashMap&lt;String, String&gt;();</div><div class="line">		timestamp = System.currentTimeMillis();</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String getKey() &#123;</div><div class="line">		return key;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String get(String k) &#123;</div><div class="line">		return data.get(k);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void put(String k, String v) &#123;</div><div class="line">		data.put(k, v);</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	public long getTimestamp() &#123;</div><div class="line">		return timestamp;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setTimestamp(long timestamp) &#123;</div><div class="line">		this.timestamp = timestamp;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setKey(String key) &#123;</div><div class="line">		this.key = key;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void remove(String k) &#123;</div><div class="line">		data.remove(k);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public HashMap&lt;String, String&gt; getData() &#123;</div><div class="line">		return data;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	@Override</div><div class="line">	public String toString() &#123;</div><div class="line">		StringBuffer buffer = new StringBuffer();</div><div class="line">		buffer.append(&quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;sent&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;key&gt;&quot;).append(key).append(&quot;&lt;/key&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;timestamp&gt;&quot;).append(timestamp).append(&quot;&lt;/timestamp&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;data&gt;&quot;);</div><div class="line">		for (String key : data.keySet()) &#123;</div><div class="line">			buffer.append(&quot;&lt;&quot; + key + &quot;&gt;&quot;).append(data.get(key)).append(</div><div class="line">					&quot;&lt;/&quot; + key + &quot;&gt;&quot;);</div><div class="line">		&#125;</div><div class="line">		buffer.append(&quot;&lt;/data&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;/sent&gt;&quot;);</div><div class="line">		return buffer.toString();</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String toXmlString() &#123;</div><div class="line">		return toString();</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.model;</div><div class="line"></div><div class="line">import java.io.Serializable;</div><div class="line">import java.util.HashMap;</div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description 服务端发送消息对象</div><div class="line"> */</div><div class="line">public class ReplyBody implements Serializable &#123;</div><div class="line"> </div><div class="line">	private static final long serialVersionUID = 1L;</div><div class="line"></div><div class="line">	/**</div><div class="line">	 * 请求key</div><div class="line">	 */</div><div class="line">	private String key;</div><div class="line">	</div><div class="line">	/**</div><div class="line">	 * 返回码</div><div class="line">	 */</div><div class="line">	private String code;</div><div class="line">	</div><div class="line">	/**</div><div class="line">	 * 返回说明</div><div class="line">	 */</div><div class="line">	private String message;</div><div class="line"></div><div class="line">	/**</div><div class="line">	 * 返回数据集合</div><div class="line">	 */</div><div class="line">	private HashMap&lt;String, String&gt; data;</div><div class="line"></div><div class="line">	</div><div class="line">	private long timestamp;</div><div class="line">	</div><div class="line">	public ReplyBody()</div><div class="line">	&#123;</div><div class="line">		data = new HashMap&lt;String, String&gt;();</div><div class="line">		timestamp = System.currentTimeMillis();</div><div class="line">	&#125;</div><div class="line">	public long getTimestamp() &#123;</div><div class="line">		return timestamp;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setTimestamp(long timestamp) &#123;</div><div class="line">		this.timestamp = timestamp;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	 </div><div class="line"></div><div class="line">	public String getKey() &#123;</div><div class="line">		return key;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setKey(String key) &#123;</div><div class="line">		this.key = key;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void put(String k, String v) &#123;</div><div class="line">		data.put(k, v);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String get(String k) &#123;</div><div class="line">		return data.get(k);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void remove(String k) &#123;</div><div class="line">		data.remove(k);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String getMessage() &#123;</div><div class="line">		return message;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setMessage(String message) &#123;</div><div class="line">		this.message = message;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public HashMap&lt;String, String&gt; getData() &#123;</div><div class="line">		return data;</div><div class="line">	&#125;</div><div class="line">  </div><div class="line">	public void setData(HashMap&lt;String, String&gt; data) &#123;</div><div class="line">		this.data = data;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	public String getCode() &#123;</div><div class="line">		return code;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setCode(String code) &#123;</div><div class="line">		this.code = code;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	</div><div class="line">	public String toString()</div><div class="line">	&#123;</div><div class="line">		</div><div class="line">		StringBuffer buffer = new StringBuffer();</div><div class="line">		buffer.append(&quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;reply&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;key&gt;&quot;).append(this.getKey()).append(&quot;&lt;/key&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;timestamp&gt;&quot;).append(timestamp).append(&quot;&lt;/timestamp&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;code&gt;&quot;).append(code).append(&quot;&lt;/code&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;message&gt;&quot;).append(message).append(&quot;&lt;/message&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;data&gt;&quot;);</div><div class="line">		for(String key:this.getData().keySet())</div><div class="line">		&#123;</div><div class="line">			buffer.append(&quot;&lt;&quot;+key+&quot;&gt;&quot;).append(this.get(key)).append(&quot;&lt;/&quot;+key+&quot;&gt;&quot;);</div><div class="line">		&#125;</div><div class="line">		buffer.append(&quot;&lt;/data&gt;&quot;);</div><div class="line">		buffer.append(&quot;&lt;/reply&gt;&quot;);</div><div class="line">		return buffer.toString();</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	</div><div class="line">	public String toXmlString()</div><div class="line">	&#123;</div><div class="line">		</div><div class="line">		return toString();</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.model;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description 消息常量</div><div class="line"> */</div><div class="line">public class Message &#123;</div><div class="line">	public static class ReturnCode &#123;</div><div class="line"></div><div class="line">		public static String CODE_404 = &quot;404&quot;; </div><div class="line"></div><div class="line">		public static String CODE_403 = &quot;403&quot;;  //该账号未绑定</div><div class="line"></div><div class="line">		public static String CODE_405 = &quot;405&quot;; //事物未定义</div><div class="line">        </div><div class="line">		public static String CODE_200 = &quot;200&quot;; //成功</div><div class="line"></div><div class="line">		public static String CODE_500 = &quot;500&quot;; //未知错误</div><div class="line"></div><div class="line">	&#125;</div><div class="line"></div><div class="line"></div><div class="line">	public static final String SESSION_KEY = &quot;account&quot;;</div><div class="line"></div><div class="line"></div><div class="line">	/**</div><div class="line">	 * 服务端心跳请求命令</div><div class="line">	 */</div><div class="line">	public static final String CMD_HEARTBEAT_REQUEST = &quot;hb_request&quot;;</div><div class="line">	/**</div><div class="line">	 * 客户端心跳响应命令</div><div class="line">	 */</div><div class="line">	public static final String CMD_HEARTBEAT_RESPONSE = &quot;hb_response&quot;;</div><div class="line"></div><div class="line"></div><div class="line">	public static class MessageType &#123;</div><div class="line">		// 用户会 踢出下线消息类型</div><div class="line">		public static String TYPE_999 = &quot;999&quot;;</div><div class="line"></div><div class="line">	&#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="实现心跳检测功能。"><a href="#实现心跳检测功能。" class="headerlink" title="实现心跳检测功能。"></a>实现心跳检测功能。</h3><hr>
<p>服务端发送的是hb_request，那么客户端就应该返回hb_response，以此来实现心跳检测。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  心跳协议的实现类</div><div class="line"> */ </div><div class="line">public class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory&#123;</div><div class="line">	private final Logger LOG=Logger.getLogger(KeepAliveMessageFactoryImpl.class);</div><div class="line">	/**</div><div class="line">	 * 客户端心跳响应命令</div><div class="line">	 */</div><div class="line">	private static  String HEARRESPONSE=Message.CMD_HEARTBEAT_RESPONSE; </div><div class="line">	/**</div><div class="line">	 * 服务端心跳请求命令</div><div class="line">	 */</div><div class="line">	private static  String HEARREQUEST=Message.CMD_HEARTBEAT_REQUEST;</div><div class="line">	</div><div class="line">	public Object getRequest(IoSession session) &#123;</div><div class="line">		LOG.warn(&quot;请求预设信息:&quot;+HEARREQUEST);</div><div class="line">		return HEARREQUEST;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public Object getResponse(IoSession session, Object message) &#123;</div><div class="line">		 LOG.warn(&quot;响应预设信息: &quot; + message);  </div><div class="line">	        /** 返回预设语句 */  </div><div class="line">	      return HEARRESPONSE;  </div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public boolean isRequest(IoSession session, Object message) &#123;</div><div class="line">		LOG.warn(&quot;请求心跳包信息: &quot; + message);  </div><div class="line">        return message.equals(HEARREQUEST); </div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public boolean isResponse(IoSession session, Object message) &#123;</div><div class="line">		 LOG.warn(&quot;响应心跳包信息: &quot; + message);  </div><div class="line">	     return message.equals(HEARRESPONSE);</div><div class="line">	   &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="实现服务端代码编写"><a href="#实现服务端代码编写" class="headerlink" title="实现服务端代码编写"></a>实现服务端代码编写</h3><hr>
<p>服务端代码这块，因为注释写的已经够详细了，所以这里就不细说了。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service;</div><div class="line"></div><div class="line">import java.io.IOException;</div><div class="line">import java.net.InetSocketAddress;</div><div class="line">import java.util.Map;</div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import org.apache.mina.core.service.IoAcceptor;</div><div class="line">import org.apache.mina.core.service.IoHandler;</div><div class="line">import org.apache.mina.core.session.IdleStatus;</div><div class="line">import org.apache.mina.core.session.IoSession;</div><div class="line">import org.apache.mina.filter.codec.ProtocolCodecFilter;</div><div class="line">import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;</div><div class="line">import org.apache.mina.filter.executor.ExecutorFilter;</div><div class="line">import org.apache.mina.filter.keepalive.KeepAliveFilter;</div><div class="line">import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;</div><div class="line">import org.apache.mina.filter.logging.LoggingFilter;</div><div class="line">import org.apache.mina.transport.socket.nio.NioSocketAcceptor;</div><div class="line">import com.pcm.mina.service.filter.KeepAliveMessageFactoryImpl;</div><div class="line"></div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  mina服务端</div><div class="line"> */</div><div class="line">public class SerNioSociketAcceptor &#123;</div><div class="line">	IoAcceptor acceptor;</div><div class="line">    IoHandler ioHandler;</div><div class="line">    int port;</div><div class="line">	//记录日志</div><div class="line">	public static Logger logger=Logger.getLogger(SerNioSociketAcceptor.class);</div><div class="line">   //创建bind()方法接收连接</div><div class="line">    public void bind() throws IOException</div><div class="line">    &#123;	</div><div class="line">       //创建 协议编码解码过滤器ProtocolCodecFilter</div><div class="line">       //设置序列化Object  可以自行设置自定义解码器</div><div class="line">     	ProtocolCodecFilter pf=new ProtocolCodecFilter(new ObjectSerializationCodecFactory());</div><div class="line">       //getFilterChain() 获取 I/O 过滤器链，可以对 I/O 过滤器进行管理，包括添加和删除 I/O 过滤器。    	</div><div class="line">    	acceptor = new NioSocketAcceptor();  </div><div class="line">    	//设置缓存大小</div><div class="line">        acceptor.getSessionConfig().setReadBufferSize(1024);  </div><div class="line">         // 设置过滤器</div><div class="line">        acceptor.getFilterChain().addLast(&quot;executor&quot;,new ExecutorFilter()); </div><div class="line">        acceptor.getFilterChain().addLast(&quot;logger&quot;,new LoggingFilter());  </div><div class="line">        acceptor.getFilterChain().addLast(&quot;codec&quot;,pf);</div><div class="line">        </div><div class="line">        KeepAliveMessageFactory kamf=new KeepAliveMessageFactoryImpl();</div><div class="line">        KeepAliveFilter kaf = new KeepAliveFilter(kamf, IdleStatus.BOTH_IDLE);</div><div class="line">        kaf.setForwardEvent(true);</div><div class="line">        kaf.setRequestInterval(30);  //本服务器为被定型心跳  即需要每30秒接受一个心跳请求  否则该连接进入空闲状态 并且发出idled方法回调</div><div class="line">        acceptor.getFilterChain().addLast(&quot;heart&quot;, kaf); </div><div class="line">        //读写通道60秒内无操作进入空闲状态</div><div class="line">        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);</div><div class="line">        //绑定逻辑处理器</div><div class="line">        acceptor.setHandler(ioHandler);  </div><div class="line">        //绑定端口</div><div class="line">        acceptor.bind(new InetSocketAddress(port));</div><div class="line">        logger.info(&quot;Mina服务端启动成功...端口号为:&quot;+port); //测试使用</div><div class="line">    &#125;</div><div class="line">    //创建unbind()方法停止监听</div><div class="line">    public void unbind()</div><div class="line">    &#123;</div><div class="line">    	acceptor.unbind();</div><div class="line">    	logger.info(&quot;服务端停止成功&quot;);</div><div class="line">    &#125;</div><div class="line">	public void setAcceptor(IoAcceptor acceptor) &#123;</div><div class="line">		this.acceptor = acceptor;</div><div class="line">	&#125;</div><div class="line">	//	设置 I/O 处理器。该 I/O 处理器会负责处理该 I/O 服务所管理的所有 I/O 会话产生的 I/O 事件。</div><div class="line">	public void setIoHandler(IoHandler ioHandler) &#123;</div><div class="line">		this.ioHandler = ioHandler;</div><div class="line">	&#125;</div><div class="line">	//设置端口</div><div class="line">	public void setPort(int port) &#123;</div><div class="line">		this.port = port;</div><div class="line">	&#125;</div><div class="line">//	获取该 I/O 服务所管理的 I/O 会话。</div><div class="line">	public  Map&lt;Long, IoSession&gt; getManagedSessions()</div><div class="line">	&#123;</div><div class="line">		return acceptor.getManagedSessions();</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<h3 id="实现session容器"><a href="#实现session容器" class="headerlink" title="实现session容器"></a>实现session容器</h3><hr>
<p>如果需要保证线程安全，可以使用 ConcurrentHashMap，作为session容器。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div><div class="line">183</div><div class="line">184</div><div class="line">185</div><div class="line">186</div><div class="line">187</div><div class="line">188</div><div class="line">189</div><div class="line">190</div><div class="line">191</div><div class="line">192</div><div class="line">193</div><div class="line">194</div><div class="line">195</div><div class="line">196</div><div class="line">197</div><div class="line">198</div><div class="line">199</div><div class="line">200</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.session;</div><div class="line"></div><div class="line">import java.io.Serializable;</div><div class="line">import java.net.InetAddress;</div><div class="line">import java.net.SocketAddress;</div><div class="line">import java.net.UnknownHostException;</div><div class="line">import org.apache.mina.core.session.IoSession;</div><div class="line"></div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  IoSession包装类  </div><div class="line"> */</div><div class="line">public class PcmSession implements Serializable&#123;</div><div class="line"></div><div class="line">	private static final long serialVersionUID = 1L;</div><div class="line">   </div><div class="line">	private transient IoSession session;</div><div class="line">	</div><div class="line">	private String gid;				//session全局ID</div><div class="line">	private Long nid;				//session在本台服务器上的ID</div><div class="line">	private String host;			//session绑定的服务器IP</div><div class="line">	private String account;			//session绑定的账号</div><div class="line">	private String message;			//session绑定账号的消息</div><div class="line">	private Long bindTime;			//登录时间</div><div class="line">	private Long heartbeat;			//心跳时间</div><div class="line"></div><div class="line"></div><div class="line">	public PcmSession()&#123;&#125;</div><div class="line">	</div><div class="line">	public PcmSession(IoSession session) &#123;</div><div class="line">		this.session = session;</div><div class="line">		this.nid = session.getId();</div><div class="line">	&#125;</div><div class="line">   </div><div class="line">	public String getGid() &#123;</div><div class="line">		return gid;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setGid(String gid) &#123;</div><div class="line">		this.gid = gid;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public Long getBindTime() &#123;</div><div class="line">		return bindTime;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setBindTime(Long bindTime) &#123;</div><div class="line">		this.bindTime = bindTime;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public Long getHeartbeat() &#123;</div><div class="line">		return heartbeat;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setHeartbeat(Long heartbeat) &#123;</div><div class="line">		this.heartbeat = heartbeat;</div><div class="line">	&#125;</div><div class="line"></div><div class="line"></div><div class="line">	public String getMessage() &#123;</div><div class="line">		return message;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setMessage(String message) &#123;</div><div class="line">		this.message = message;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String getAccount() &#123;</div><div class="line">		return account;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setAccount(String account) &#123;</div><div class="line">		this.account = account;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public String getHost() &#123;</div><div class="line">		return host;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setHost(String host) &#123;</div><div class="line">		this.host = host;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void setIoSession(IoSession session) &#123;</div><div class="line">		this.session = session;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public IoSession getIoSession() &#123;</div><div class="line">		return session;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line"></div><div class="line">//  将键为 key，值为 value的用户自定义的属性存储到 I/O 会话中。</div><div class="line">	public void setAttribute(String key, Object value) &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			session.setAttribute(key, value);</div><div class="line">		&#125;</div><div class="line">		</div><div class="line">	&#125;</div><div class="line"></div><div class="line"></div><div class="line">	public boolean containsAttribute(String key) &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			</div><div class="line">			return session.containsAttribute(key);</div><div class="line">		&#125;</div><div class="line">		return false;</div><div class="line">	&#125;</div><div class="line">	//	从 I/O 会话中获取键为 key的用户自定义的属性。</div><div class="line">	public Object getAttribute(String key) &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			</div><div class="line">			return session.getAttribute(key);</div><div class="line">		&#125;</div><div class="line">		</div><div class="line">		return null;</div><div class="line">	&#125;</div><div class="line">	//从 I/O 会话中删除键为 key的用户自定义的属性。</div><div class="line">	public void removeAttribute(String key) &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			session.removeAttribute(key);</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">		</div><div class="line"></div><div class="line">	public SocketAddress getRemoteAddress() &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			return session.getRemoteAddress();</div><div class="line">		&#125;		</div><div class="line">		return null;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">/*	 将消息对象 message发送到当前连接的对等体。该方法是异步的，当消息被真正发送到对等体的时候，</div><div class="line">	IoHandler.messageSent(IoSession,Object)会被调用。如果需要的话，</div><div class="line">	也可以等消息真正发送出去之后再继续执行后续操作。*/</div><div class="line">	public void write(Object msg) &#123;</div><div class="line">		if(session!=null)</div><div class="line">		&#123;</div><div class="line">			session.write(msg).isWritten();	</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	public boolean isConnected() &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			return session.isConnected();</div><div class="line">		&#125;</div><div class="line">		return false;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public boolean  isLocalhost()</div><div class="line">	&#123;</div><div class="line">		try &#123;</div><div class="line">			String ip = InetAddress.getLocalHost().getHostAddress();</div><div class="line">			return ip.equals(host);</div><div class="line">		&#125; catch (UnknownHostException e) &#123;</div><div class="line">			e.printStackTrace();</div><div class="line">		&#125;</div><div class="line">		return false;</div><div class="line">		 </div><div class="line">	&#125;</div><div class="line">	</div><div class="line">/* 关闭当前连接。如果参数 immediately为 true的话，</div><div class="line"> * 连接会等到队列中所有的数据发送请求都完成之后才关闭；否则的话就立即关闭。 </div><div class="line"> */	</div><div class="line">	public void close(boolean immediately) &#123;</div><div class="line">		if(session!=null)&#123;</div><div class="line">			session.close(immediately);</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public boolean equals(Object message) &#123;</div><div class="line">        </div><div class="line">		if (message instanceof PcmSession) &#123;</div><div class="line">			</div><div class="line">			PcmSession t = (PcmSession) message;</div><div class="line">			if( t.nid!=null &amp;&amp; nid!=null)</div><div class="line">			&#123;</div><div class="line">				return  t.nid.longValue()==nid.longValue() &amp;&amp; t.host.equals(host);</div><div class="line">			&#125; </div><div class="line">		&#125;  </div><div class="line">		return false;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	</div><div class="line">	public String  toString()</div><div class="line">	&#123;</div><div class="line">		StringBuffer buffer = new   StringBuffer();</div><div class="line">		buffer.append(&quot;&#123;&quot;);</div><div class="line">	buffer.append(&quot;\&quot;&quot;).append(&quot;gid&quot;).append(&quot;\&quot;:&quot;).append(&quot;\&quot;&quot;).append(gid).append(&quot;\&quot;&quot;).append(&quot;,&quot;);</div><div class="line">		buffer.append(&quot;\&quot;&quot;).append(&quot;nid&quot;).append(&quot;\&quot;:&quot;).append(nid).append(&quot;,&quot;);</div><div class="line">		buffer.append(&quot;\&quot;&quot;).append(&quot;host&quot;).append(&quot;\&quot;:&quot;).append(&quot;\&quot;&quot;).append(host).append(&quot;\&quot;&quot;).append(&quot;,&quot;);</div><div class="line">		buffer.append(&quot;\&quot;&quot;).append(&quot;account&quot;).append(&quot;\&quot;:&quot;).append(&quot;\&quot;&quot;).append(account).append(&quot;\&quot;&quot;).append(&quot;,&quot;);</div><div class="line">		buffer.append(&quot;\&quot;&quot;).append(&quot;bindTime&quot;).append(&quot;\&quot;:&quot;).append(bindTime).append(&quot;,&quot;);</div><div class="line">		buffer.append(&quot;\&quot;&quot;).append(&quot;heartbeat&quot;).append(&quot;\&quot;:&quot;).append(heartbeat);</div><div class="line">		buffer.append(&quot;&#125;&quot;);</div><div class="line">		return buffer.toString();</div><div class="line">		</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.session;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  客户端的session管理接口</div><div class="line"> */</div><div class="line">public interface SessionManager &#123;</div><div class="line">	/**</div><div class="line">	 * 添加新的session</div><div class="line">	 */</div><div class="line">	public void addSession(String account,PcmSession session);</div><div class="line">	</div><div class="line">	/**</div><div class="line">	 * </div><div class="line">	 * @param account 客户端session的 key 一般可用 用户账号来对应session</div><div class="line">	 * @return</div><div class="line">	 */</div><div class="line">	PcmSession getSession(String account);</div><div class="line">	</div><div class="line">    /**</div><div class="line">	 * 删除session</div><div class="line">	 * @param session</div><div class="line">	 */</div><div class="line">    public void  removeSession(PcmSession session);</div><div class="line">  </div><div class="line">    /**</div><div class="line">  	 * 删除session</div><div class="line">  	 * @param account</div><div class="line">  	 */</div><div class="line">    public void  removeSession(String account);</div><div class="line">    </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.session;</div><div class="line"></div><div class="line">import java.util.HashMap;</div><div class="line">import java.util.concurrent.atomic.AtomicInteger;</div><div class="line">import com.pcm.mina.service.model.Message;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  自带默认 session管理实现</div><div class="line"> */</div><div class="line">public class DefaultSessionManager implements SessionManager&#123;</div><div class="line"></div><div class="line">	 private static HashMap&lt;String,PcmSession&gt; sessions =new  HashMap&lt;String,PcmSession&gt;();</div><div class="line">	 private static final AtomicInteger connectionsCounter = new AtomicInteger(0);</div><div class="line"></div><div class="line">	public void addSession(String account, PcmSession session) &#123;</div><div class="line">		if(session !=null)&#123;</div><div class="line">			sessions.put(account, session);</div><div class="line">			connectionsCounter.incrementAndGet();</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	public PcmSession getSession(String account) &#123;</div><div class="line">		return sessions.get(account);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	public void removeSession(PcmSession session) &#123;</div><div class="line">		sessions.remove(session.getAttribute(Message.SESSION_KEY));</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	public void removeSession(String account) &#123;</div><div class="line">		sessions.remove(account);</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="实现业务逻辑处理器。"><a href="#实现业务逻辑处理器。" class="headerlink" title="实现业务逻辑处理器。"></a>实现业务逻辑处理器。</h3><hr>
<p>因为注释写的已经够详细了，所以这里就不细说了。<br>做了简单业务逻辑处理，如有需要可以自行更改。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.handler;</div><div class="line"></div><div class="line">import java.net.InetSocketAddress;</div><div class="line">import java.util.HashMap;</div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import org.apache.mina.core.service.IoHandlerAdapter;</div><div class="line">import org.apache.mina.core.session.IdleStatus;</div><div class="line">import org.apache.mina.core.session.IoSession;</div><div class="line">import org.springframework.stereotype.Component;</div><div class="line">import com.pcm.mina.service.RequestHandler;</div><div class="line">import com.pcm.mina.service.model.Message;</div><div class="line">import com.pcm.mina.service.model.ReplyBody;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line">import com.pcm.mina.service.session.PcmSession;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  I/O 处理器 客户端请求的入口，所有请求都首先经过它分发处理 业务逻辑实现</div><div class="line"> */ </div><div class="line"></div><div class="line">@Component(&quot;sercixeMainHandler&quot;)</div><div class="line">public class ServiceMainHandler extends IoHandlerAdapter&#123;</div><div class="line">	protected final Logger logger = Logger.getLogger(ServiceMainHandler.class);</div><div class="line">	</div><div class="line">    //本地handler请求</div><div class="line">	private HashMap&lt;String, RequestHandler&gt; handlers = new HashMap&lt;String, RequestHandler&gt;();</div><div class="line">			</div><div class="line">	//出错时</div><div class="line">	@Override</div><div class="line">	public void exceptionCaught(IoSession session, Throwable cause)&#123;</div><div class="line">		logger.error(&quot;exceptionCaught()... from &quot;+session.getRemoteAddress());</div><div class="line">		logger.error(cause);</div><div class="line">		cause.printStackTrace();</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	//接收到消息时</div><div class="line">	@Override</div><div class="line">	public void messageReceived(IoSession iosession,Object message)&#123;		</div><div class="line">		logger.info(&quot;服务端接收到的消息...&quot;+message.toString());</div><div class="line">		if(message instanceof SentBody)&#123;</div><div class="line">			SentBody sent=(SentBody) message;</div><div class="line">			ReplyBody rb=new ReplyBody();</div><div class="line">			PcmSession session=new PcmSession(iosession);</div><div class="line">			String key=sent.getKey();</div><div class="line">			if(&quot;quit&quot;.equals(sent.get(&quot;message&quot;)))&#123; //服务器断开的条件</div><div class="line">				try &#123;</div><div class="line">					sessionClosed(iosession);</div><div class="line">				&#125; catch (Exception e) &#123;</div><div class="line">					rb.setCode(Message.ReturnCode.CODE_500);</div><div class="line">					e.printStackTrace();</div><div class="line">				&#125;</div><div class="line">			&#125;else&#123;</div><div class="line">			//根据key的不同调用不同的handler</div><div class="line">			RequestHandler rhandler=handlers.get(key);</div><div class="line">			if(rhandler==null)&#123;//如果没有这个handler</div><div class="line">				rb.setCode(Message.ReturnCode.CODE_405);</div><div class="line">				rb.setMessage(&quot;服务端未定义!&quot;);</div><div class="line">			&#125;else&#123;//有的话</div><div class="line">				rb=rhandler.process(session, sent);</div><div class="line">			&#125;</div><div class="line">			&#125;</div><div class="line">			if(rb !=null)&#123;</div><div class="line">				rb.setKey(key);</div><div class="line">				session.write(rb);</div><div class="line">				logger.info(&quot;服务端发送的消息: &quot; + rb.toString());</div><div class="line">			&#125;</div><div class="line">		</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	//发送消息</div><div class="line">	@Override</div><div class="line">	public void messageSent(IoSession session, Object message) throws Exception &#123;</div><div class="line">   //	session.close(); //发送成功后主动断开与客户端的连接 实现短连接</div><div class="line">       logger.info(&quot;服务端发送信息成功...&quot;);</div><div class="line">	    &#125;</div><div class="line">	</div><div class="line">	//建立连接时</div><div class="line">	@Override</div><div class="line">	public void sessionCreated(IoSession session) throws Exception &#123;</div><div class="line">		 	InetSocketAddress sa=(InetSocketAddress)session.getRemoteAddress();</div><div class="line">			String address=sa.getAddress().getHostAddress(); //访问的ip</div><div class="line">			session.setAttribute(&quot;address&quot;, address);</div><div class="line">			//将连接的客户端ip保存到map集合中</div><div class="line">			SentBody body=new SentBody();</div><div class="line">			body.put(&quot;address&quot;, address);</div><div class="line">			logger.info(&quot;访问的ip:&quot;+address);</div><div class="line">	    &#125;</div><div class="line">	</div><div class="line">	//关闭连接时   </div><div class="line">	@Override</div><div class="line">	public void sessionClosed(IoSession iosession) throws Exception &#123;</div><div class="line">			PcmSession session=new PcmSession(iosession);</div><div class="line">			logger.debug(&quot;sessionClosed()... from &quot;+session.getRemoteAddress());</div><div class="line">			try &#123;</div><div class="line">				RequestHandler hand=handlers.get(&quot;client_closs&quot;);</div><div class="line">				if(hand !=null &amp;&amp; session.containsAttribute(Message.SESSION_KEY))&#123;</div><div class="line">					hand.process(session, null);</div><div class="line">				&#125;</div><div class="line">			&#125; catch (Exception e) &#123;</div><div class="line">				e.printStackTrace();</div><div class="line">			&#125;</div><div class="line">			session.close(true);  </div><div class="line">			logger.info(&quot;连接关闭&quot;);</div><div class="line">	    &#125;</div><div class="line"></div><div class="line">	//空闲时</div><div class="line">	@Override</div><div class="line">	public void sessionIdle(IoSession session, IdleStatus status) throws Exception &#123;</div><div class="line">		logger.debug(&quot;sessionIdle()... from &quot;+session.getRemoteAddress());</div><div class="line">	    &#125;</div><div class="line">	</div><div class="line">	//打开连接时   </div><div class="line">	@Override</div><div class="line">	 public void sessionOpened(IoSession session) throws Exception &#123;</div><div class="line">		 	logger.info(&quot;开启连接...&quot;);</div><div class="line">	    &#125;</div><div class="line">	</div><div class="line">	public HashMap&lt;String, RequestHandler&gt; getHandlers() &#123;</div><div class="line">		return handlers;</div><div class="line">	&#125;</div><div class="line">	public void setHandlers(HashMap&lt;String, RequestHandler&gt; handlers) &#123;</div><div class="line">		this.handlers = handlers;</div><div class="line">	&#125; </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="实现业务逻辑代码。"><a href="#实现业务逻辑代码。" class="headerlink" title="实现业务逻辑代码。"></a>实现业务逻辑代码。</h3><hr>
<p>目前实现了绑定，推送以及关闭逻辑代码。如有需要，可自行增加。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service;</div><div class="line"></div><div class="line">import com.pcm.mina.service.model.ReplyBody;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line">import com.pcm.mina.service.session.PcmSession;</div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  请求处理接口,所有的请求必须实现此接口</div><div class="line"> */</div><div class="line">public interface RequestHandler &#123;</div><div class="line">	public abstract ReplyBody process(PcmSession session,SentBody message);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.handler;</div><div class="line"></div><div class="line">import java.net.InetAddress;</div><div class="line">import java.util.UUID;</div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import com.pcm.mina.service.RequestHandler;</div><div class="line">import com.pcm.mina.service.model.Message;</div><div class="line">import com.pcm.mina.service.model.ReplyBody;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line">import com.pcm.mina.service.session.DefaultSessionManager;</div><div class="line">import com.pcm.mina.service.session.PcmSession;</div><div class="line">import com.pcm.util.ContextHolder;</div><div class="line"> </div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  账号绑定实现</div><div class="line"> */ </div><div class="line">public class BindHandler implements RequestHandler &#123;</div><div class="line">	protected final Logger logger = Logger.getLogger(BindHandler.class);</div><div class="line">	public ReplyBody process(PcmSession newSession, SentBody message) &#123;</div><div class="line">		ReplyBody reply = new ReplyBody();</div><div class="line">		DefaultSessionManager sessionManager= ((DefaultSessionManager) ContextHolder.getBean(&quot;PcmSessionManager&quot;));</div><div class="line">		try &#123; </div><div class="line">			String account = message.get(Message.SESSION_KEY);</div><div class="line">			newSession.setAccount(account);</div><div class="line">			newSession.setMessage(message.get(&quot;message&quot;));</div><div class="line">			newSession.setGid(UUID.randomUUID().toString());</div><div class="line">			newSession.setHost(InetAddress.getLocalHost().getHostAddress());</div><div class="line">            //第一次设置心跳时间为登录时间</div><div class="line">			newSession.setBindTime(System.currentTimeMillis());</div><div class="line">			newSession.setHeartbeat(System.currentTimeMillis());</div><div class="line">			/**</div><div class="line">			 * 由于客户端断线服务端可能会无法获知的情况，客户端重连时，需要关闭旧的连接</div><div class="line">			 */</div><div class="line">			PcmSession oldSession  = sessionManager.getSession(account);</div><div class="line">            //如果是账号已经在另一台终端登录。则让另一个终端下线</div><div class="line">			if(oldSession!=null&amp;&amp;!oldSession.equals(newSession))</div><div class="line">			&#123;</div><div class="line">					oldSession.removeAttribute(Message.SESSION_KEY);</div><div class="line">					ReplyBody rb = new ReplyBody();</div><div class="line">					rb.setCode(Message.MessageType.TYPE_999);//强行下线消息类型</div><div class="line">					rb.put(Message.SESSION_KEY, account);</div><div class="line">					if(!oldSession.isLocalhost())</div><div class="line">					&#123;</div><div class="line">						/*</div><div class="line">						判断当前session是否连接于本台服务器，如不是发往目标服务器处理</div><div class="line">						MessageDispatcher.execute(rb, oldSession.getHost());</div><div class="line">						*/</div><div class="line">					&#125;else</div><div class="line">					&#123;</div><div class="line">						oldSession.write(rb);</div><div class="line">						oldSession.close(true);</div><div class="line">						oldSession = null;</div><div class="line">					&#125;</div><div class="line">					oldSession = null;</div><div class="line">			&#125;</div><div class="line">			if(oldSession==null)</div><div class="line">			&#123;</div><div class="line">				sessionManager.addSession(account, newSession);</div><div class="line">			&#125;</div><div class="line">			</div><div class="line">			reply.setCode(Message.ReturnCode.CODE_200);</div><div class="line">		&#125; catch (Exception e) &#123;</div><div class="line">			reply.setCode(Message.ReturnCode.CODE_500);</div><div class="line">			e.printStackTrace();</div><div class="line">		&#125;</div><div class="line">		logger.debug(&quot;绑定账号:&quot; +message.get(Message.SESSION_KEY)+&quot;-----------------------------&quot; +reply.getCode());</div><div class="line">		return reply;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.handler;</div><div class="line"></div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import com.pcm.mina.service.RequestHandler;</div><div class="line">import com.pcm.mina.service.model.Message;</div><div class="line">import com.pcm.mina.service.model.ReplyBody;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line">import com.pcm.mina.service.session.DefaultSessionManager;</div><div class="line">import com.pcm.mina.service.session.PcmSession;</div><div class="line">import com.pcm.util.ContextHolder;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  推送消息</div><div class="line"> */ </div><div class="line">public class PushMessageHandler implements RequestHandler &#123;</div><div class="line"></div><div class="line">	protected final Logger logger = Logger.getLogger(PushMessageHandler.class);</div><div class="line">	public ReplyBody process(PcmSession ios, SentBody sent) &#123;</div><div class="line">		ReplyBody reply = new ReplyBody();</div><div class="line">		String account=(String) sent.getData().get(Message.SESSION_KEY);</div><div class="line">		DefaultSessionManager sessionManager=(DefaultSessionManager) ContextHolder.getBean(&quot;PcmSessionManager&quot;);</div><div class="line">		PcmSession session=sessionManager.getSession(account);</div><div class="line">		if(session !=null)&#123;</div><div class="line">			sent.remove(Message.SESSION_KEY);</div><div class="line">			reply.setKey(sent.getKey());</div><div class="line">			reply.setMessage(&quot;推送的消息&quot;);</div><div class="line">			reply.setData(sent.getData());</div><div class="line">			reply.setCode(Message.ReturnCode.CODE_200); </div><div class="line">			session.write(reply); //转发获取的消息</div><div class="line">			logger.info(&quot;推送的消息是:&quot;+reply.toString());</div><div class="line">		&#125;else&#123;</div><div class="line">			reply.setCode(Message.ReturnCode.CODE_403);</div><div class="line">			reply.setMessage(&quot;推送失败&quot;);</div><div class="line">		&#125;</div><div class="line">		return reply;</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.service.handler;</div><div class="line"></div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import com.pcm.mina.service.RequestHandler;</div><div class="line">import com.pcm.mina.service.model.Message;</div><div class="line">import com.pcm.mina.service.model.ReplyBody;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line">import com.pcm.mina.service.session.DefaultSessionManager;</div><div class="line">import com.pcm.mina.service.session.PcmSession;</div><div class="line">import com.pcm.util.ContextHolder;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description  断开连接，清除session</div><div class="line"> */</div><div class="line">public class SessionClosedHandler implements RequestHandler &#123;</div><div class="line">	protected final Logger logger = Logger.getLogger(SessionClosedHandler.class);</div><div class="line">	public ReplyBody process(PcmSession ios, SentBody message) &#123;</div><div class="line"></div><div class="line">		DefaultSessionManager sessionManager  =  ((DefaultSessionManager) ContextHolder.getBean(&quot;PcmSessionManager&quot;));</div><div class="line"></div><div class="line">		if(ios.getAttribute(Message.SESSION_KEY)==null)</div><div class="line">		&#123;</div><div class="line">			return null;</div><div class="line">		&#125;</div><div class="line">	    String account = ios.getAttribute(Message.SESSION_KEY).toString();</div><div class="line">	    sessionManager.removeSession(account);</div><div class="line">		return null;</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="spring配置"><a href="#spring配置" class="headerlink" title="spring配置"></a>spring配置</h3><hr>
<p>可以将过滤器添加到spring这块，包括心跳设置。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line">&lt;!-- spring集成mina --&gt;</div><div class="line">		&lt;!-- 设置 I/O 接受器，并指定接收到请求后交给 myHandler 进行处理 --&gt; </div><div class="line">		&lt;bean id=&quot;customEditorConfigurer&quot; class=&quot;org.springframework.beans.factory.config.CustomEditorConfigurer&quot;&gt;</div><div class="line">		   &lt;property name=&quot;customEditors&quot; &gt;</div><div class="line">		     &lt;map&gt;</div><div class="line">		       &lt;entry key=&quot;java.net.SocketAddress&quot;  value=&quot;org.apache.mina.integration.beans.InetSocketAddressEditor&quot;/&gt;</div><div class="line">		     &lt;/map&gt;</div><div class="line">		   &lt;/property&gt;</div><div class="line">		 &lt;/bean&gt;</div><div class="line">		 </div><div class="line">		 &lt;!-- handlers事件 --&gt;</div><div class="line">		&lt;bean id=&quot;IoHandler&quot; class=&quot;com.pcm.mina.service.handler.ServiceMainHandler&quot;&gt;</div><div class="line">			&lt;property name=&quot;handlers&quot;&gt;</div><div class="line">				&lt;map&gt;</div><div class="line">					&lt;entry key=&quot;client_bind&quot;&gt;  &lt;!-- 创建连接 --&gt;</div><div class="line">						&lt;bean class=&quot;com.pcm.mina.service.handler.BindHandler&quot;&gt;&lt;/bean&gt;</div><div class="line">					&lt;/entry&gt;</div><div class="line">					&lt;entry key=&quot;client_closs&quot;&gt;  &lt;!--断开清除会话  --&gt;</div><div class="line">						&lt;bean class=&quot;com.pcm.mina.service.handler.SessionClosedHandler&quot;&gt;&lt;/bean&gt;</div><div class="line">					&lt;/entry&gt;</div><div class="line">					&lt;entry key=&quot;client_push&quot;&gt;  &lt;!--在线推送消息  --&gt;</div><div class="line">						&lt;bean class=&quot;com.pcm.mina.service.handler.PushMessageHandler&quot;&gt;&lt;/bean&gt;</div><div class="line">					&lt;/entry&gt;</div><div class="line">				&lt;/map&gt;</div><div class="line">			&lt;/property&gt;</div><div class="line">		&lt;/bean&gt;</div><div class="line">		</div><div class="line">		 &lt;!-- IoAccepter，绑定到1255端口 --&gt;</div><div class="line">		  &lt;!-- 通过 init-method指明了当 I/O 接受器创建成功之后，调用其 bind方法来接受连接；通过 destroy-method声明了当其被销毁的时候，调用其 unbind来停止监听 --&gt;</div><div class="line">	    &lt;bean id=&quot;SerNioSociketAcceptor&quot;  class=&quot;com.pcm.mina.service.SerNioSociketAcceptor&quot; </div><div class="line">	    init-method=&quot;bind&quot; destroy-method=&quot;unbind&quot;&gt;  </div><div class="line">	         &lt;property name=&quot;port&quot; value=&quot;1255&quot; /&gt; </div><div class="line">			 &lt;property name=&quot;ioHandler&quot; ref=&quot;IoHandler&quot; /&gt; </div><div class="line">	    &lt;/bean&gt;</div><div class="line">	     </div><div class="line">	     &lt;!--spring动态获取bean实现  --&gt;</div><div class="line">	    &lt;bean id=&quot;ContextHolder&quot; class=&quot;com.pcm.util.ContextHolder&quot;&gt;&lt;/bean&gt;</div><div class="line">	   	&lt;bean id=&quot;PcmSessionManager&quot; class=&quot;com.pcm.mina.service.session.DefaultSessionManager&quot;/&gt;</div></pre></td></tr></table></figure></p>
<h2 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h2><p>===</p>
<h3 id="编写业务逻辑处理器"><a href="#编写业务逻辑处理器" class="headerlink" title="编写业务逻辑处理器"></a>编写业务逻辑处理器</h3><hr>
<p>几乎和服务端一样，这里因为测试，所以就从简了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.client.MinaDemo;</div><div class="line"></div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import org.apache.mina.core.service.IoHandlerAdapter;</div><div class="line">import org.apache.mina.core.session.IoSession;</div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description 客户端handle</div><div class="line"> */</div><div class="line">public class MinaClientHandler extends IoHandlerAdapter &#123;</div><div class="line">    private static Logger logger = Logger.getLogger(MinaClientHandler.class);</div><div class="line"></div><div class="line">    @Override</div><div class="line">    public void messageReceived(IoSession session, Object message)</div><div class="line">            throws Exception &#123;</div><div class="line">         String msg = message.toString();</div><div class="line">    //    logger.info(&quot;客户端A接收的数据:&quot; + msg);</div><div class="line">      System.out.println(&quot;客户端A接收的数据:&quot; + msg);</div><div class="line">       if(msg.equals(&quot;hb_request&quot;))&#123;</div><div class="line">        logger.warn(&quot;客户端A成功收到心跳包:hb_request&quot;);</div><div class="line">       	session.write(&quot;hb_response&quot;);</div><div class="line">       	logger.warn(&quot;客户端A成功发送心跳包:hb_response&quot;);</div><div class="line">       &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    @Override</div><div class="line">    public void exceptionCaught(IoSession session, Throwable cause)</div><div class="line">            throws Exception &#123;</div><div class="line">        logger.error(&quot;发生错误...&quot;, cause);</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="编写客户端程序。"><a href="#编写客户端程序。" class="headerlink" title="编写客户端程序。"></a>编写客户端程序。</h3><hr>
<p>也几乎和服务端一致，为了简单使用，编写main方法。<br>注:客户端和服务端的过滤器要一致。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div></pre></td><td class="code"><pre><div class="line">package com.pcm.mina.client.MinaDemo;</div><div class="line"></div><div class="line">import java.net.InetSocketAddress;</div><div class="line">import org.apache.log4j.Logger;</div><div class="line">import org.apache.mina.core.future.ConnectFuture;</div><div class="line">import org.apache.mina.core.service.IoConnector;</div><div class="line">import org.apache.mina.core.session.IoSession;</div><div class="line">import org.apache.mina.filter.codec.ProtocolCodecFilter;</div><div class="line">import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;</div><div class="line">import org.apache.mina.transport.socket.nio.NioSocketConnector;</div><div class="line">import com.pcm.mina.service.model.SentBody;</div><div class="line"></div><div class="line"></div><div class="line">/**</div><div class="line"> * @author ZERO</div><div class="line"> * @Description mina 客户端</div><div class="line"> */</div><div class="line">	public class MinaClient &#123;</div><div class="line">	    private static Logger logger = Logger.getLogger(MinaClient.class);</div><div class="line">	    private static String HOST = &quot;127.0.0.1&quot;;</div><div class="line">	    private static int PORT = 1255;</div><div class="line">	    private static  IoConnector connector=new NioSocketConnector();</div><div class="line">	    private static   IoSession session;</div><div class="line">	    public static IoConnector getConnector() &#123;</div><div class="line">			return connector;</div><div class="line">		&#125;</div><div class="line"></div><div class="line">		public static void setConnector(IoConnector connector) &#123;</div><div class="line">			MinaClient.connector = connector;</div><div class="line">		&#125;</div><div class="line"></div><div class="line">		/* </div><div class="line">	    * 测试服务端与客户端程序！</div><div class="line">	    a. 启动服务端，然后再启动客户端</div><div class="line">	    b. 服务端接收消息并处理成功;</div><div class="line">	    */</div><div class="line">	    @SuppressWarnings(&quot;deprecation&quot;)</div><div class="line">		public static void main(String[] args) &#123;</div><div class="line">	    	   // 设置链接超时时间</div><div class="line">	        connector.setConnectTimeout(30000);</div><div class="line">	        // 添加过滤器  可序列话的对象 </div><div class="line">	        connector.getFilterChain().addLast(</div><div class="line">	                &quot;codec&quot;,</div><div class="line">	                new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));</div><div class="line">	        // 添加业务逻辑处理器类</div><div class="line">	        connector.setHandler(new MinaClientHandler());</div><div class="line">	        ConnectFuture future = connector.connect(new InetSocketAddress(</div><div class="line">	                HOST, PORT));// 创建连接</div><div class="line">	        future.awaitUninterruptibly();// 等待连接创建完成</div><div class="line">	        session = future.getSession();// 获得session</div><div class="line">	        </div><div class="line">	     	bindstart();</div><div class="line">	   // 	pushstart();</div><div class="line">	    &#125;</div><div class="line">	    </div><div class="line">	    public static void bindstart()&#123;</div><div class="line">	    	logger.info(&quot;客户端A绑定服务端&quot;);</div><div class="line">	        try &#123;</div><div class="line">	            SentBody sy=new SentBody();</div><div class="line">	            sy.put(&quot;message&quot;, &quot;这是个测试账号&quot;);</div><div class="line">	            sy.put(&quot;account&quot;, &quot;123456&quot;);</div><div class="line">	            sy.setKey(&quot;client_bind&quot;);</div><div class="line">	            session.write(sy);// 发送消息</div><div class="line">	            System.out.println(&quot;客户端A与服务端建立连接成功...发送的消息为:&quot;+sy);</div><div class="line">	      //      logger.info(&quot;客户端A与服务端建立连接成功...发送的消息为:&quot;+sy);</div><div class="line">	        &#125; catch (Exception e) &#123;</div><div class="line">	        	e.printStackTrace();</div><div class="line">	            logger.error(&quot;客户A端链接异常...&quot;, e);</div><div class="line">	        &#125;</div><div class="line">	        session.getCloseFuture().awaitUninterruptibly();// 等待连接断开</div><div class="line">	        connector.dispose();</div><div class="line">	    &#125;</div><div class="line">｝</div></pre></td></tr></table></figure>
<p>代码就先告一段落。客户端也可以通过socket和mina进行数据传输，这里就不贴代码了。<br>spring整合mina，暂时就到这了。项目我放到了github上，地址:<a href="https://github.com/xuwujing/springMina/tree/master" target="_blank" rel="external">https://github.com/xuwujing/springMina/tree/master</a><br>如果感觉不错，希望可以给个star。</p>
<p>版权声明:<br>作者：虚无境<br>博客园出处：<a href="http://www.cnblogs.com/xuwujing" target="_blank" rel="external">http://www.cnblogs.com/xuwujing</a><br>CSDN出处：<a href="http://blog.csdn.net/qazwsxpcm" target="_blank" rel="external">http://blog.csdn.net/qazwsxpcm</a>　　　　<br>个人博客出处：<a href="http://www.panchengming.com" target="_blank" rel="external">http://www.panchengming.com</a><br>原创不易，转载请标明出处，谢谢！</p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>
     
    <div>
	 +
	  
<div style="text-align:center;color: #ccc;font-size:14px;">
------ 本文结束 ------</div>
<br/>
<div style="border: 1px solid black">
<div style="margin-left:10px">
<span style="font-weight:blod">版权声明</span>
<!-- <img src="/images/xuwujing.png" > -->
<br/>
<p style="font-size: 10px;line-height: 30px"><a href="http://www.panchengming.com/" style="color:#258FC6">xuwujing's Notes</a> by <a href="http://www.panchengming.com/" style="color:#258FC6">ChengMing Pan</a> is licensed under a <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/" style="color:#258FC6">Creative Commons BY-NC-ND 4.0 International License</a>.<br/>
由<a href="http://www.panchengming.com/" style="color:#258FC6">虚无境</a>创作并维护的<a href="http://www.panchengming.com/" style="color:#258FC6">xuwujing's Notes</a>博客采用<a href="https://creativecommons.org/licenses/by-nc-nd/4.0/" style="color:#258FC6">创作共用保留署名-非商业-禁止演绎4.0国际许可证</a>。<br/>
本文首发于<a href="http://www.panchengming.com/" style="color:#258FC6">xuwujing's Notes</a> 博客（ <a href="http://www.panchengming.com/" style="color:#258FC6">http://www.panchengming.com/</a> ），版权所有，侵权必究。</p>
</div>
</div>

	
	</div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/java/" rel="tag"># java</a>
          
            <a href="/tags/spring/" rel="tag"># spring</a>
          
            <a href="/tags/mina/" rel="tag"># mina</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2017/06/04/pancm27/" rel="next" title="Linux 常用命令">
                <i class="fa fa-chevron-left"></i> Linux 常用命令
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/06/25/pancm28/" rel="prev" title="Web 项目更改项目名">
                Web 项目更改项目名 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/xuwujing.png"
               alt="虚无境" />
          <p class="site-author-name" itemprop="name">虚无境</p>
           
              <p class="site-description motion-element" itemprop="description">The way of the future!</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives/">
                <span class="site-state-item-count">136</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">30</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">59</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/xuwujing" target="_blank" title="github">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  github
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://blog.csdn.net/qazwsxpcm?viewmode=list" target="_blank" title="csdn">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  csdn
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://home.cnblogs.com/u/xuwujing/" target="_blank" title="cnblogs">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  cnblogs
                </a>
              </span>
            
          
        </div>

        
        

        
        
          <div class="links-of-blogroll motion-element links-of-blogroll-inline">
            <div class="links-of-blogroll-title">
              <i class="fa  fa-fw fa-globe"></i>
              
            </div>
            <ul class="links-of-blogroll-list">
              
                <li class="links-of-blogroll-item">
                  <a href="http://www.woainia.site/" title="woainia" target="_blank">woainia</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://cmsblogs.com/" title="chenssy" target="_blank">chenssy</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://italker.imisty.cn" title="xiaowu" target="_blank">xiaowu</a>
                </li>
              
            </ul>
          </div>
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#spring集成mina"><span class="nav-number">1.</span> <span class="nav-text">spring集成mina</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#效果实现图"><span class="nav-number">1.1.</span> <span class="nav-text">效果实现图</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#服务端启动成功后，-客户端A绑定服务端。"><span class="nav-number">1.1.1.</span> <span class="nav-text">服务端启动成功后， 客户端A绑定服务端。</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#客户端B向服务端发送信息，请求服务端向客户端A推送消息"><span class="nav-number">1.1.2.</span> <span class="nav-text">客户端B向服务端发送信息，请求服务端向客户端A推送消息</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#客户端A受到服务端转发的客户端B的消息"><span class="nav-number">1.1.3.</span> <span class="nav-text">客户端A受到服务端转发的客户端B的消息</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#服务端心跳检测的实现"><span class="nav-number">1.1.4.</span> <span class="nav-text">服务端心跳检测的实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#代码的目录结构"><span class="nav-number">1.1.5.</span> <span class="nav-text">代码的目录结构</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#服务端"><span class="nav-number">2.</span> <span class="nav-text">服务端</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#首先实现数据传输对象、消息常量的代码编写。"><span class="nav-number">2.1.</span> <span class="nav-text">首先实现数据传输对象、消息常量的代码编写。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现心跳检测功能。"><span class="nav-number">2.2.</span> <span class="nav-text">实现心跳检测功能。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现服务端代码编写"><span class="nav-number">2.3.</span> <span class="nav-text">实现服务端代码编写</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现session容器"><span class="nav-number">2.4.</span> <span class="nav-text">实现session容器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现业务逻辑处理器。"><span class="nav-number">2.5.</span> <span class="nav-text">实现业务逻辑处理器。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现业务逻辑代码。"><span class="nav-number">2.6.</span> <span class="nav-text">实现业务逻辑代码。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#spring配置"><span class="nav-number">2.7.</span> <span class="nav-text">spring配置</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#客户端"><span class="nav-number">3.</span> <span class="nav-text">客户端</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#编写业务逻辑处理器"><span class="nav-number">3.1.</span> <span class="nav-text">编写业务逻辑处理器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#编写客户端程序。"><span class="nav-number">3.2.</span> <span class="nav-text">编写客户端程序。</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">虚无境</span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>

  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
 | 
本站总访问量<span id="busuanzi_value_site_pv"></span>次
 | 
本站访客数<span id="busuanzi_value_site_uv"></span>人次
<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=857896&auto=0&height=66"></iframe>



        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.1"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.1"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.1"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.1"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.1"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.1"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.1"></script>



  


  




	





  





  





  






  





  

  

  

  

  

  

</body>
</html>
